/******************************************************************************
 * Copyright (C) 2017 Chengdu Dlhd information industry co. LTD.
 * All Rights Reserved.
 * 本软件为成都顶联互动信息产业有限公司开发研制。未经本公司正式书面同意，其他任何个人、团体不得使用、复制、修改或发布本软件.
 *****************************************************************************/
package net.dgg.dggcloud.service.jrcrm.service.customer;

import net.dgg.dggcloud.core.minidao.hibernate.dao.IGenericBaseCommonDao;
import net.dgg.dggcloud.core.util.MapToBeanUtils;
import net.dgg.dggcloud.core.util.NJCodeUtil;
import net.dgg.dggcloud.core.util.StringUtils;
import net.dgg.dggcloud.service.common.base.service.BaseService;
import net.dgg.dggcloud.service.common.exception.BizException;
import net.dgg.dggcloud.service.jrcrm.constant.CustomerConstant;
import net.dgg.dggcloud.service.jrcrm.dao.customer.ContactDao;
import net.dgg.dggcloud.service.jrcrm.entity.customer.Contact;
import net.dgg.dggcloud.service.jrcrm.entity.customer.Customer;
import net.dgg.dggcloud.service.entity.user.User;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.dialect.CUBRIDDialect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.beans.IntrospectionException;
import java.lang.reflect.InvocationTargetException;
import java.util.*;

/**
 * 联系人业务处理
 * @ClassName: ContactService
 * @Author: 周潮
 * @Date: 2017年11月03 14:40:18
 * @Version V1.0
 */

@Service
public class ContactService extends BaseService {
    @Resource(name = "miniDaoHiberCommonDao")
    protected IGenericBaseCommonDao repository;

    @Autowired
    private ContactDao contactDao;
    @Resource
    private CustomerService customerService;
    @Resource
    private NJCodeUtil njCodeUtil;

    /**
     * 查询客户联系人
     * @param cusId 客户id
     * @param status 1查询全部联系人，2查询可用联系人，3查询作废联系人，4查询主联系人
     * @param cusId 客户id
     * @return
     */
    public List<Contact> getContactByCusId(Long cusId, Integer status){
        //默认查询启用状态的联系人
        String statusParam = "";
        switch (status){
            case 1:
                break;
            case 2:
                    statusParam = " and status in ('" + CustomerConstant.CUS_CONTACT_STATUS_1 + "','" + CustomerConstant.CUS_CONTACT_STATUS_2 + "')";//主联系人、可用
                break;
            case 3:
                statusParam = " and status = '" + CustomerConstant.CUS_CONTACT_STATUS_0 + "'";//作废
                break;
            case 4:
                statusParam = " and status = '" + CustomerConstant.CUS_CONTACT_STATUS_2 + "'";//主联系人
                break;
            default:
                statusParam = " and status in ('" + CustomerConstant.CUS_CONTACT_STATUS_1 + "','" + CustomerConstant.CUS_CONTACT_STATUS_2 + "')";//主联系人、可用
                break;
        }
        Query query = repository.getSession().createQuery("from Contact where  customerId = ? " + statusParam);
        query.setParameter(0,cusId);
        return  query.list();
    }

    /**
     * 新增联系人
     * @param map
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void saveContact(Map map){
        if(null == map.get("contact")){
            throw new BizException("新增联系人失败！联系人信息为空！", 10005);
        }
        if(null == map.get("User")){
            throw new BizException("新增联系人失败！操作人信息为空！", 10005);
        }
        User user = (User) map.get("User");
        Contact contact = (Contact) map.get("contact");
        if(null == contact.getCustomerId()){
            throw new BizException("新增联系人失败！客户不存在！", 10005);
        }
        Customer customer = repository.get(Customer.class, contact.getCustomerId());
        if(null == customer){
            throw new BizException("新增联系人失败！客户不存在！", 10005);
        }
        Map params = new HashMap();
        params.put("contactWay", StringUtils.isEmpty(contact.getContactWay()) ? CustomerConstant.CUS_CONTACT_WAY_MOBILE : contact.getContactWay());
        params.put("customerNumber", contact.getNo());
        Integer repeatCount = contactDao.queryContactCountForJudgeRepeat(params);
        if(repeatCount >0 ) {
            throw new BizException("新增联系人失败！该号码已存在，不能重复添加！", 10005);
        }
        long id = this.keyWorker.nextId();
        contact.setId(id);
        contact.setCreateUser(user);
        if(StringUtils.isNotEmpty(contact.getStatus())){
            if(contact.getStatus().equals(CustomerConstant.CUS_CONTACT_STATUS_2)){//如果是修改为主联系人
                //如果是主联系人，则更新客户上面的主联系人信息，并排除其他主联系人
                updateCusMainContact(contact, user, customer);
            }
        }else{
            contact.setStatus(CustomerConstant.CUS_CONTACT_STATUS_1);//默认联系人状态为可用
            repository.save(contact);
        }
        customerService.saveCustomerRecord(customer.getId(), customer.getNo(), Contact.TABLE_NAME, contact.getId(), CustomerConstant.CUS_OPERATE_CONTACT_SAVE, user.getId(), "新增联系人");
    }

    /**
     * 更新联系人
     * @param map
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void updateContact(Map map){
        if(null == map.get("contact")){
            throw new BizException("更新联系人失败！联系人信息为空！", 10005);
        }
        if(null == map.get("User")){
            throw new BizException("更新联系人失败！操作人信息为空！", 10005);
        }
        User user = (User) map.get("User");
        Contact contact = (Contact) map.get("contact");
        if(null == contact.getId()){
            throw new BizException("更新联系人失败！联系人信息为空！", 10005);
        }
        Contact c = repository.get(Contact.class, contact.getId());
        if(null == contact.getCustomerId()){
            throw new BizException("更新联系人失败！客户不存在！", 10005);
        }
        Customer customer = repository.get(Customer.class, contact.getCustomerId());
        if(null == customer){
            throw new BizException("更新联系人失败！客户不存在！", 10005);
        }
        if(StringUtils.isNotEmpty(contact.getStatus())){
            if(c.getStatus().equals(CustomerConstant.CUS_CONTACT_STATUS_2)){//如果是修改为主联系人
                contact.setUpdaterUser(user);
                //如果是主联系人，则更新客户上面的主联系人信息，并排除其他主联系人
                updateCusMainContact(c, user, customer);
            }else{
                c.setStatus(contact.getStatus());
                c.setUpdaterUser(user);
                repository.saveOrUpdate(c);
            }
        }else{
            c.setStatus(CustomerConstant.CUS_CONTACT_STATUS_1);//默认联系人状态为可用
            c.setUpdaterUser(user);
            repository.saveOrUpdate(c);
        }
        customerService.saveCustomerRecord(customer.getId(), customer.getNo(), Contact.TABLE_NAME, contact.getId(), CustomerConstant.CUS_OPERATE_CONTACT_UPDATE, user.getId(), "修改联系人信息");
    }

    /**
     * 更新联系人基础信息
     * @param map
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void updateContactBaseInfo(Map map){
        if(null == map.get("contactId")){
            throw new BizException("更新联系人失败！联系人信息为空！", 10005);
        }
        if(null == map.get("contactName")){
            throw new BizException("更新联系人失败！姓名不能为空！", 10005);
        }
        if(null == map.get("User")){
            throw new BizException("更新联系人失败！操作人信息为空！", 10005);
        }
        User user = (User) map.get("User");
        Long contactId = Long.parseLong(map.get("contactId").toString());
        String contactName = map.get("contactName").toString();
        Contact contact = repository.get(Contact.class, contactId);

        if(null == contact){
            throw new BizException("更新联系人失败！联系人信息为空！", 10005);
        }
        Customer customer = repository.get(Customer.class, contact.getCustomerId());
        if(null == customer){
            throw new BizException("更新联系人失败！找不到对应的客户！", 10005);
        }
        contact.setName(contactName);
        contact.setUpdaterUser(user);
        if(contact.getStatus().equals(CustomerConstant.CUS_CONTACT_STATUS_2)){
            customer.setMainContactName(contactName);
        }
        customerService.saveCustomerRecord(customer.getId(), customer.getNo(), Contact.TABLE_NAME, contact.getId(), CustomerConstant.CUS_OPERATE_CONTACT_UPDATE, user.getId(), "修改联系人信息");
    }

    /**
     * 更新联系人状态
     * @param map
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void updateContactStatus(Map map){
        if(null == map.get("contactId")){
            throw new BizException("更新联系人状态失败！联系人信息为空！", 10005);
        }
        if(null == map.get("User")){
            throw new BizException("更新联系人状态失败！操作人信息为空！", 10005);
        }
        if(null == map.get("status")){
            throw new BizException("更新联系人状态失败！联系人信息为空！", 10005);
        }
        User user = (User) map.get("User");
        Long id = Long.parseLong(map.get("contactId").toString());
        String status = map.get("status").toString();
        Contact contact = repository.get(Contact.class, id);
        if(null == contact){
            throw new BizException("更新联系人状态失败！联系人信息为空！", 10005);
        }
        Customer customer = repository.get(Customer.class, contact.getCustomerId());
        if(null == customer){
            throw new BizException("更新联系人状态失败！客户不存在！", 10005);
        }
        if(status.equals(CustomerConstant.CUS_CONTACT_STATUS_2)){
            contact.setUpdaterUser(user);
            //如果是主联系人，则更新客户上面的主联系人信息，并排除其他主联系人
            contact = updateCusMainContact(contact, user, customer);
            customerService.saveCustomerRecord(customer.getId(), customer.getNo(), Contact.TABLE_NAME, contact.getId(), CustomerConstant.CUS_OPERATE_CONTACT_UPDATE, user.getId(), "修改联系人信息");
        }else if(status.equals(CustomerConstant.CUS_CONTACT_STATUS_0)){
            //查询该客户全部联系人,如果只存在一个联系人则不允许作废该联系人
            List<Contact> contactList = this.getContactByCusId(customer.getId(), 2);
            if(null != contactList && contactList.size() == 1 ){
                throw new BizException("作废联系人失败！该客户仅有当前一个联系人！", 10005);
            }
            contact.setStatus(status);
            contact.setUpdaterUser(user);
            repository.saveOrUpdate(contact);
            customerService.saveCustomerRecord(customer.getId(), customer.getNo(), Contact.TABLE_NAME, contact.getId(), CustomerConstant.CUS_OPERATE_CONTACT_UPDATE, user.getId(), "修改联系人信息");
        }else{
            contact.setStatus(status);
            contact.setUpdaterUser(user);
            repository.saveOrUpdate(contact);
            customerService.saveCustomerRecord(customer.getId(), customer.getNo(), Contact.TABLE_NAME, contact.getId(), CustomerConstant.CUS_OPERATE_CONTACT_UPDATE, user.getId(), "修改联系人信息");
        }
    }

    /**
     * 根据传入联系人信息，更新客户上的主联系人信息，并且排查客户其他联系人是否存在主联系人，如果存在则更新其状态为可用（保证客户的主联系人唯一性）
     * @param contact 联系人对象
     * @param user 操作人
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public Contact updateCusMainContact(Contact contact, User user, Customer customer){
        if(null == customer){
            throw new BizException("更新主联系人失败！客户不存在！", 10005);
        }
        customer.setMainContactId(contact.getId());
        customer.setMainContactNo(contact.getNo());
        customer.setMainContactNoBak(njCodeUtil.decrypt(contact.getNo()));
        customer.setMainContactName(contact.getName());
        customer.setUpdaterUser(user);
        repository.saveOrUpdate(customer);
        //查询该客户对应主联系人
        List<Contact> contactList = this.getContactByCusId(customer.getId(), 4);
        //如果有联系人则判断是否还有其他联系人为主联系人，如果是则修改状态为可用
        if(null != contactList){
            for (Contact c: contactList) {
                if(c.getId().longValue() == contact.getId()){
                    repository.getSession().evict(c);//清除session中相同id的对象
                }
                //排除当前设置的联系人外，其余联系人状态如果还有是主联系人的则修改为可用状态
                if(null!=c.getStatus() && c.getStatus().equals(CustomerConstant.CUS_CONTACT_STATUS_2) && c.getId().longValue() != contact.getId()){
                    c.setStatus(CustomerConstant.CUS_CONTACT_STATUS_1);//设置为可用
                    c.setUpdaterUser(user);
                    repository.saveOrUpdate(c);
                }
            }
        }
        contact.setStatus(CustomerConstant.CUS_CONTACT_STATUS_2);//设置状态为主联系人
        contact.setRelationshipOfCus("ORF_JDRGX_1");
        repository.saveOrUpdate(contact);
        return contact;
    }

    /**
     * mq推送联系人新增或修改联系人消息时，调用该方法进行业务处理
     * @param obj 要处理的联系人数据
     */
    public void saveOrUpdateBaseContact(Map obj) {
        Contact contact = null;
        try {
            contact = (Contact) MapToBeanUtils.MapToBean(Contact.class, obj);
            if(null == contact.getCustomerId()){
                return;
            }
            Customer customer = repository.get(Customer.class, contact.getCustomerId());
            if(CustomerConstant.contactWaySet.contains(contact.getContactWay()) && null != customer){//判断联系方式是否存在于iboss
                String status = "";
                if(null == obj.get("status")){
                    status = CustomerConstant.CUS_CONTACT_STATUS_1;
                }else {
                    status = Integer.parseInt(obj.get("status").toString()) == 1 ? CustomerConstant.CUS_CONTACT_STATUS_1 : CustomerConstant.CUS_CONTACT_STATUS_0;
                }
                contact.setStatus(status);
                Contact updateContact = repository.get(Contact.class, contact.getId());
                if(null == updateContact){
                    repository.save(contact);
                }else {
                    updateContact.setStatus(contact.getStatus());
                    updateContact.setNo(contact.getNo());//联系人号码
                    updateContact.setNoBak(njCodeUtil.decrypt(contact.getNo()));//联系人号码
                    updateContact.setName(contact.getName());//联系人姓名
                    updateContact.setContactWay(contact.getContactWay());//联系方式
                    updateContact.setCustomerId(contact.getCustomerId());//客户id
                    updateContact.setUpdaterName("Base同步");
                    repository.getSession().evict(contact);
                    repository.saveOrUpdate(updateContact);
                }
            }
        } catch (IntrospectionException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }
}
